package com.anti.modular.sys.notice.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import com.anti.commom.api.Result;
import com.anti.commom.core.exception.BusinessException;
import com.anti.core.context.login.LoginContextHolder;
import com.anti.jdbc.DBUtils;
import com.anti.jdbc.support.page.PageParam;
import com.anti.jdbc.support.page.PageResult;
import com.anti.modular.sys.auth.pojo.SysLoginUser;
import com.anti.modular.sys.notice.entity.SysNotice;
import com.anti.modular.sys.notice.entity.SysNoticeUser;
import com.anti.modular.sys.notice.enums.NoticeStatusEnum;
import com.anti.modular.sys.notice.enums.NoticeUserStatusEnum;
import com.anti.modular.sys.notice.enums.SysNoticeExceptionEnum;
import com.anti.modular.sys.notice.param.SysNoticeParam;
import com.anti.modular.sys.notice.result.SysNoticeDetailResult;
import com.anti.modular.sys.notice.result.SysNoticeReceiveResult;
import com.anti.modular.sys.notice.service.SysNoticeService;
import com.anti.modular.sys.notice.service.SysNoticeUserService;
import com.anti.modular.sys.user.service.SysUserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Description TODO
 * @Author anTi
 * @Date 2021-3-25
 */
@Service
public class SysNoticeServiceImpl implements SysNoticeService {
    @Resource
    DBUtils dbUtils;
    @Resource
    SysNoticeUserService sysNoticeUserService;
    @Resource
    SysUserService sysUserService;

    @Override
    public Result getNotices() {
        String sql="select * from sys_notice where status=1";
        return Result.data(dbUtils.query(sql,SysNoticeReceiveResult.class));
    }

    @Override
    public PageResult page(PageParam pageParam, SysNoticeParam sysNoticeParam) {
        StringBuilder sb=new StringBuilder("select * from sys_notice where status <> 3");
        ArrayList<Object> params = CollectionUtil.newArrayList();
        if (ObjectUtil.isNotNull(sysNoticeParam)) {
            //根据标题或内容模糊查询
            if (ObjectUtil.isNotEmpty(sysNoticeParam.getSearchValue())) {
                sb.append(" and ( tittle like ? or content like ?) ");
                params.add("%"+sysNoticeParam.getSearchValue()+"%");
                params.add("%"+sysNoticeParam.getSearchValue()+"%");
            }
            //根据类型查询
            if (ObjectUtil.isNotEmpty(sysNoticeParam.getType())) {
                sb.append(" and type=?");
                params.add(sysNoticeParam.getType());
            }
        }
        return dbUtils.query(pageParam,sb.toString(),SysNoticeReceiveResult.class,params.toArray());
    }

    @Override
    public void add(SysNoticeParam sysNoticeParam) {
        //校验参数，检查状态是否正确
        checkParam(sysNoticeParam, true);
        SysNotice sysNotice = new SysNotice();
        BeanUtil.copyProperties(sysNoticeParam, sysNotice);
        SysLoginUser sysLoginUser = LoginContextHolder.me().getSysLoginUser();
        sysNotice.setPublicUserId(sysLoginUser.getId());
        sysNotice.setPublicUserName(sysLoginUser.getName());
        sysNotice.setPublicOrgId(sysLoginUser.getLoginEmpInfo().getOrgId());
        sysNotice.setPublicOrgName(sysLoginUser.getLoginEmpInfo().getOrgName());
        //如果是发布，则设置发布时间
        if (NoticeStatusEnum.PUBLIC.getCode().equals(sysNotice.getStatus())) {
            sysNotice.setPublicTime(new Date());
        }
        sysNotice.setCreateTime(new Date());
        sysNotice.setCreateUser(sysLoginUser.getId());
        String key = dbUtils.insertKey(sysNotice).toString();
        sysNotice.setId(Long.parseLong(key));
        //通知到的人
        List<Long> noticeUserIdList = sysNoticeParam.getNoticeUserIdList();
        Integer noticeUserStatus = NoticeUserStatusEnum.UNREAD.getCode();
        sysNoticeUserService.add(sysNotice.getId(), noticeUserIdList, noticeUserStatus);
    }

    @Override
    public void delete(SysNoticeParam sysNoticeParam) {
        SysNotice sysNotice = this.querySysNotice(sysNoticeParam);
        Integer status = sysNotice.getStatus();
        if (!NoticeStatusEnum.DRAFT.getCode().equals(status) && !NoticeStatusEnum.CANCEL.getCode().equals(status)) {
            throw new BusinessException(SysNoticeExceptionEnum.NOTICE_CANNOT_DELETE);
        }
        sysNotice.setStatus(NoticeStatusEnum.DELETED.getCode());
        sysNotice.setUpdateTime(new Date());
        sysNotice.setUpdateUser(LoginContextHolder.me().getSysLoginUserId());
        dbUtils.update(sysNotice);
    }

    @Override
    public void edit(SysNoticeParam sysNoticeParam) {
        SysNotice sysNotice = this.querySysNotice(sysNoticeParam);
        //校验参数，检查状态是否正确
        checkParam(sysNoticeParam, true);
        //非草稿状态
        Integer status = sysNotice.getStatus();
        if (!NoticeStatusEnum.DRAFT.getCode().equals(status)) {
            throw new BusinessException(SysNoticeExceptionEnum.NOTICE_CANNOT_EDIT);
        }
        BeanUtil.copyProperties(sysNoticeParam, sysNotice);
        //如果是发布，则设置发布时间
        if (NoticeStatusEnum.PUBLIC.getCode().equals(sysNotice.getStatus())) {
            sysNotice.setPublicTime(new Date());
        }
        sysNotice.setUpdateTime(new Date());
        sysNotice.setUpdateUser(LoginContextHolder.me().getSysLoginUserId());
        dbUtils.update(sysNotice);
        //通知到的人
        List<Long> noticeUserIdList = sysNoticeParam.getNoticeUserIdList();
        Integer noticeUserStatus = NoticeUserStatusEnum.UNREAD.getCode();
        sysNoticeUserService.edit(sysNotice.getId(), noticeUserIdList, noticeUserStatus);
    }

    @Override
    public SysNoticeDetailResult detail(SysNoticeParam sysNoticeParam) {
        SysNotice sysNotice = this.querySysNotice(sysNoticeParam);
        Long id = sysNotice.getId();
        //获取通知到的用户
        List<SysNoticeUser> sysNoticeUserList = sysNoticeUserService.getSysNoticeUserListByNoticeId(id);
        List<Long> noticeUserIdList = CollectionUtil.newArrayList();
        List<Dict> noticeUserReadInfoList = CollectionUtil.newArrayList();
        SysNoticeDetailResult sysNoticeResult = new SysNoticeDetailResult();
        BeanUtil.copyProperties(sysNotice, sysNoticeResult);
        if (ObjectUtil.isNotEmpty(sysNoticeUserList)) {
            sysNoticeUserList.forEach(sysNoticeUser -> {
                //遍历通知到的用户，并构造
                noticeUserIdList.add(sysNoticeUser.getUserId());
                Dict dict = Dict.create();
                dict.put("userId", sysNoticeUser.getUserId());
                dict.put("userName", sysUserService.getNameByUserId(sysNoticeUser.getUserId()));
                dict.put("readStatus", sysNoticeUser.getStatus());
                dict.put("readTime", sysNoticeUser.getReadTime());
                noticeUserReadInfoList.add(dict);
            });
        }
        sysNoticeResult.setNoticeUserIdList(noticeUserIdList);
        sysNoticeResult.setNoticeUserReadInfoList(noticeUserReadInfoList);
        //如果该条通知公告为已发布，则将当前用户的该条通知公告设置为已读
        if (sysNotice.getStatus().equals(NoticeStatusEnum.PUBLIC.getCode())) {
            sysNoticeUserService.saveRead(sysNotice.getId(),
                    LoginContextHolder.me().getSysLoginUserId(), NoticeUserStatusEnum.READ.getCode());
        }
        return sysNoticeResult;
    }

    @Override
    public void saveChangeStatus(SysNoticeParam sysNoticeParam) {
        SysNotice sysNotice = this.querySysNotice(sysNoticeParam);
        //校验参数，检查状态是否正确
        checkParam(sysNoticeParam, false);
        sysNotice.setStatus(sysNoticeParam.getStatus());
        //如果是撤回，则设置撤回时间
        if (NoticeStatusEnum.CANCEL.getCode().equals(sysNotice.getStatus())) {
            sysNotice.setCancelTime(new Date());
        } else if (NoticeStatusEnum.PUBLIC.getCode().equals(sysNotice.getStatus())) {
            //如果是发布，则设置发布时间
            sysNotice.setPublicTime(new Date());
        }
        dbUtils.update(sysNotice);
    }

    @Override
    public PageResult received(PageParam pageParam, SysNoticeParam sysNoticeParam) {
        //查询当前用户的
        StringBuilder sb=new StringBuilder("select sys_notice.* from sys_notice_user,sys_notice where sys_notice.status <> 3 and sys_notice_user.notice_id=sys_notice.id and  sys_notice_user.user_id=?");
        ArrayList<Object> params = CollectionUtil.newArrayList();
        params.add(LoginContextHolder.me().getSysLoginUserId());
        if (ObjectUtil.isNotNull(sysNoticeParam)) {
            //根据标题或内容模糊查询
            if (ObjectUtil.isNotEmpty(sysNoticeParam.getSearchValue())) {
                sb.append(" and ( sys_notice.title like ? or sys_notice.content like ? )");
                params.add("%"+sysNoticeParam.getSearchValue()+"%");
                params.add("%"+sysNoticeParam.getSearchValue()+"%");
            }
            //根据类型查询
            if (ObjectUtil.isNotEmpty(sysNoticeParam.getType())) {
                sb.append(" and sys_notice.type=?");
                params.add(sysNoticeParam.getType());
            }
        }
        PageResult pageResult = dbUtils.query(pageParam, sb.toString(), SysNoticeReceiveResult.class, params.toArray());
        return pageResult;
    }


    /**
     * 校验参数，判断状态是否正确
     */
    private void checkParam(SysNoticeParam sysNoticeParam, boolean isAddOrEdit) {
        //保存或编辑时，传递的状态参数应为草稿，或发布
        Integer status = sysNoticeParam.getStatus();
        if (isAddOrEdit) {
            if (!NoticeStatusEnum.DRAFT.getCode().equals(status) &&
                    !NoticeStatusEnum.PUBLIC.getCode().equals(status)) {
                throw new BusinessException(SysNoticeExceptionEnum.NOTICE_STATUS_ERROR);
            }
        } else {
            //修改状态时，传递的状态参数应为撤回或删除或发布
            if (!NoticeStatusEnum.CANCEL.getCode().equals(status) &&
                    !NoticeStatusEnum.DELETED.getCode().equals(status) &&
                    !NoticeStatusEnum.PUBLIC.getCode().equals(status)) {
                throw new BusinessException(SysNoticeExceptionEnum.NOTICE_STATUS_ERROR);
            }
        }

    }
    /**
     * 获取系统通知公告

     */
    private SysNotice querySysNotice(SysNoticeParam sysNoticeParam) {
        SysNotice sysNotice = dbUtils.get("select * from sys_notice where id =?",SysNotice.class,sysNoticeParam.getId());
        if (ObjectUtil.isNull(sysNotice)) {
            throw new BusinessException(SysNoticeExceptionEnum.NOTICE_NOT_EXIST);
        }
        return sysNotice;
    }

}
